﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using JasRibbonApplicatie.Model;
using JasRibbonApplicatie.Classes;
using JasRibbonApplicatie.UserControls;
using JasRibbonApplicatie;

namespace JasRibbonApplicatie.Views
{
    /// <summary>
    /// Interaction logic for Scannen.xaml
    /// </summary>
    public partial class Scannen : Page
    {
        private MainWindow mainPageRef;
        private List<Status> toegelatenStatussenAfhalen = new List<Status>();
        private List<Status> toegelatenStatussenInleveren = new List<Status>();
        private static AanvraagModel am = new AanvraagModel();
        private static MateriaalModel mm = new MateriaalModel();
        private static GebruikerModel gm = new GebruikerModel();

        private Magazijnier huidigeMagazijnier;
        private Aanvraag huidigeAanvraag;
        private bool inleveren;

        private List<OntleningData> ontleningDataList = new List<OntleningData>();

        private enum MessageType
        {
            Info,
            Warning,
            Error
        }

        public Scannen()
        {
            InitializeComponent();
            mainPageRef = Login.Instance.MainWindowReference;

            #region set huidige magazijnier & check bevoegheid
            var magazijnierRecordsGebruiker = Login.Instance.User.magazijniers.Where(m => m.einde == null || m.einde > DateTime.Now);
            if (magazijnierRecordsGebruiker.Count() > 0)
            {
                huidigeMagazijnier = magazijnierRecordsGebruiker.First();
            }
            else
            {
                huidigeMagazijnier = null;
                Console.WriteLine("geen magazijnier:");
                //geen magazijnier?
                //contolleer rechten.
                if (Login.Instance.User.rechten.omschrijving == "Beheerder")
                {
                    //bevoegd? Disable scannen tab, enable rest, move to aanvragen.

                    mainPageRef.materiaalTab.Visibility = Visibility.Visible;
                    mainPageRef.aanvragenTab.Visibility = Visibility.Visible;
                    mainPageRef.gebruikersTab.Visibility = Visibility.Visible;
                    mainPageRef.planningTab.Visibility = Visibility.Visible;
                    mainPageRef.materiaalTab.IsEnabled = true;
                    mainPageRef.aanvragenTab.IsEnabled = true;
                    mainPageRef.gebruikersTab.IsEnabled = true;
                    mainPageRef.planningTab.IsEnabled = true;

                    mainPageRef.aanvragenTab.IsSelected = true;

                    mainPageRef.scannenTab.Visibility = Visibility.Collapsed;
                    mainPageRef.scannenTab.IsEnabled = false;
                }
                else
                {
                    //niet bevoegd afmelden.
                    mainPageRef.Logoff_Click(null, null);
                }
            }
            #endregion


            #region set toegelaten statussen

            toegelatenStatussenAfhalen.Add(am.getStatus("definietieve goedkeuring"));
            toegelatenStatussenAfhalen.Add(am.getStatus("materiaal buiten"));

            toegelatenStatussenInleveren.Add(am.getStatus("materiaal buiten"));

            #endregion

            if (mainPageRef.Inleveren != null)
            {
                inleveren = mainPageRef.Inleveren.Value;
            }
            else
            {
                throw new NotImplementedException("Scannen.xaml.cs: Error inleveren not set in mainpage");
            }

            huidigeAanvraag = mainPageRef.SelectedAanvraag;
            //check if valid aanvraag
            if ((inleveren && !toegelatenStatussenInleveren.Contains(huidigeAanvraag.status)) ||
               (!inleveren && !toegelatenStatussenAfhalen.Contains(huidigeAanvraag.status)))
            {
                throw new NotImplementedException("Scannen.xaml.cs: Invalid aanvraag status");
            }

            //fill datagrid
            List<Ontlening> oudeOntleningen = huidigeAanvraag.ontlening.ToList();
            ontleningDataList = fillDataGrid(oudeOntleningen);
            ontleningenDataList.ItemSource = ontleningDataList;

        }

        private List<OntleningData> fillDataGrid(List<Ontlening> oudeOntleningen)
        {
            List<OntleningData> nieuweOntleningDataList = new List<OntleningData>();
            foreach (var m in huidigeAanvraag.materiaalbestelling)
            {
                for (int n = 0; n < m.aantalGoedgekeurd; n++)
                {
                    //Haal alle streepjescodes voor dat materiaaltype op
                    var validStreepjescodes = from mat in m.materiaaltype.materiaal
                                              select mat.streepjescode;
                    //Geef een array van ontleningen waar de streepjescode van het huidige materiaaltype is
                    var ontl = from o in oudeOntleningen
                               where validStreepjescodes.Contains(o.streepjescode)
                               select o;

                    /* Als die array ontleingen bevat:
                     *    voeg 1 toe aan de nieuweOntleningenDataList
                     *    en wis 1 van de oudeOntleningen lijst
                     * Anders
                     *    maak een nieuwe ontleningenData en voeg toe aan de nieuweOntleningenDataList
                     */
                    if (ontl.Count() > 0)
                    {
                        nieuweOntleningDataList.Add(new OntleningData(m.materiaaltype, ontl.First()));
                        oudeOntleningen.Remove(ontl.First());
                    }
                    else
                    {
                        nieuweOntleningDataList.Add(new OntleningData(m.materiaaltype));
                    }

                    //same for toebehoren
                    foreach (var t in m.materiaaltype.toebehorenmateriaal)
                    {
                        for (int i = 0; i < t.aantal; i++)
                        {
                            //Haal alle streepjescodes voor dat toebehorentype op
                            validStreepjescodes = from toeb in t.toebehorentype.toebehoren
                                                  select toeb.streepjescode;
                            //Geef een array van ontleningen waar de streepjescode van het huidige toebehorentype is
                            ontl = from o in oudeOntleningen
                                   where validStreepjescodes.Contains(o.streepjescode)
                                   select o;

                            /* Als die array ontleingen bevat:
                             *    voeg 1 toe aan de nieuweOntleningenDataList
                             *    en wis 1 van de oudeOntleningen lijst
                             * Anders
                             *    maak een nieuwe ontleningenData en voeg toe aan de nieuweOntleningenDataList
                             */
                            if (ontl.Count() > 0)
                            {
                                nieuweOntleningDataList.Add(new OntleningData(t.toebehorentype, ontl.First()));
                                oudeOntleningen.Remove(ontl.First());
                            }
                            else
                            {
                                nieuweOntleningDataList.Add(new OntleningData(t.toebehorentype));
                            }
                        }
                    }
                }
            }
            return nieuweOntleningDataList;
        }

        private void scanTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {

            TextBox textbox = (TextBox)sender;
            String inhoud = textbox.Text.ToLower();

            if (inhoud.Length == MateriaalModel.LENGTH_SCANCODES)
            {
                // invoer niet meer toelaten (proces kan tijdje duren)
                // gebruiker kan en mag terwijl niets doen...

                textbox.IsEnabled = false;
                laatstGescandTextBox.Text = inhoud;

                bool toegevoegd;
                using (OverrideCursor cursor = new OverrideCursor(Cursors.Wait)) // wachtcursor tonen
                {
                    try
                    {
                        checkValidCodeAndUpdate(inhoud);
                        displayMessage("Object Toegevoegd", MessageType.Info);
                        toegevoegd = true;
                    } catch(InvalidOperationException ex){
                        toegevoegd = false;
                        displayMessage(ex.Message, MessageType.Warning);
                    } catch (Exception ex) {
                        toegevoegd = false;
                        displayMessage(ex.Message, MessageType.Error);
                    }
                }

                if (toegevoegd) saveModels();

                textbox.Text = "";
                textbox.IsEnabled = true;
                textbox.Focus(); // zodat je terug iets kunt inscannen
            }

        }

        private void saveModels()
        {
            ontleningDataList = fillDataGrid(huidigeAanvraag.ontlening.ToList());
            ontleningenDataList.ItemSource = ontleningDataList;

            mm.OpslaanWijzigingen();
            am.OpslaanWijzigingen();
            gm.OpslaanWijzigingen();
        }

        private void checkValidCodeAndUpdate(string inhoud)
        {
            inhoud = inhoud.ToLower();
            if (inhoud.Substring(0, 1) == "m" || inhoud.Substring(0, 1) == "t")
            {
                if (inleveren)
                {
                    var ontleningData = from o in ontleningDataList
                                        where o.Ontlening.streepjescode == inhoud
                                        select o;
                    if (ontleningData.Count() > 0)
                    {
                        var o = ontleningData.First();
                        o.Ontlening.magazijnierInlevering = gm.GetMagazijnier(Login.Instance.User);
                        o.Ontlening.tijdstip_inlevering = DateTime.Now;
                        huidigeAanvraag.ontlening.Remove(
                            huidigeAanvraag.ontlening.Where(ontl => ontl.streepjescode == inhoud).Select(ontl => ontl).First()
                        );
                        huidigeAanvraag.ontlening.Add(o.Ontlening);
                    }
                    else
                    {
                        throw new InvalidOperationException("Object niet ontleend");
                    }
                }
                else
                {
                    //lijst ophalen van reeds gescande codes (in deze ontlening)

                    var ontleningCodes = getCodes(ontleningDataList);
                    if (!ontleningCodes.Contains(inhoud))
                    {
                        if (inhoud.Substring(0, 1) == "m")
                        {
                            var materiaal = mm.GetMateriaalByScancode(inhoud);
                            if (materiaal == null) throw new NotSupportedException("Dit object bestaat niet! (Niet in onze databank althans.)");
                            var ontleningData = from o in ontleningDataList
                                                where o.Ontlening == null && o.Id == materiaal.materiaaltype.materiaalType_id
                                                select o;

                            if (ontleningData.Count() > 0)
                            {
                                var o = ontleningData.First();
                                o.Ontlening = new Ontlening()
                                {
                                    aanvraag_id = 1,
                                    streepjescode = inhoud,
                                    magazijnier_id_afhaling = gm.GetMagazijnier(Login.Instance.User).magazijnier_id,
                                    tijdstip_afhaling = DateTime.Now
                                };
                                huidigeAanvraag.ontlening.Add(o.Ontlening);
                            }
                            else
                            {
                                throw new InvalidOperationException("Dees hebde ni nodig maatje!");
                            }
                        }
                        else if (inhoud.Substring(0, 1) == "t")
                        {
                            var toebehoren = mm.GetToebehorenByScancode(inhoud);
                            if (toebehoren == null) throw new NotSupportedException("Dit object bestaat niet! (Niet in onze databank althans.)");
                            var ontleningData = from o in ontleningDataList
                                                where o.Ontlening == null && o.Id == toebehoren.toebehorentype.toebehorenType_id
                                                select o;

                            if (ontleningData.Count() > 0)
                            {
                                var o = ontleningData.First();
                                o.Ontlening = new Ontlening()
                                {
                                    aanvraag_id = 1,
                                    streepjescode = inhoud,
                                    magazijnier_id_afhaling = gm.GetMagazijnier(Login.Instance.User).magazijnier_id,
                                    tijdstip_afhaling = DateTime.Now
                                };
                                huidigeAanvraag.ontlening.Add(o.Ontlening);
                            }
                            else
                            {
                                throw new InvalidOperationException("Dees hebde ni nodig maatje!");
                            }
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException("Code al gescand");
                    }
                }
            }
        }

        private string[] getCodes(List<OntleningData> ontleningDataList)
        {
            List<string> codes = new List<string>();
            foreach (var ontleningData in ontleningDataList)
                if (ontleningData.Ontlening != null)
                    codes.Add(ontleningData.Ontlening.streepjescode);
            return codes.ToArray<string>();
        }

        private void displayMessage(string message, MessageType type)
        {
            probleemGroupbox.Visibility = Visibility.Visible;
            probleemTextBox.Text = message;
            ImageSourceConverter isc= new ImageSourceConverter();
            switch(type){
                case MessageType.Info:
                    probleemGroupbox.Header = "Info";
                    probleemTextBox.Foreground = Brushes.Black;
                    probleemImage.Source = isc.ConvertFromString("pack://application:,,,/JasRibbonApplicatie;component/Images/info.png") as ImageSource;
                    break;
                case MessageType.Warning:
                    probleemGroupbox.Header = "Opgelet!";
                    probleemTextBox.Foreground = Brushes.Orange;
                    probleemImage.Source = isc.ConvertFromString("pack://application:,,,/JasRibbonApplicatie;component/Images/warning.png") as ImageSource;
                    break;
                case MessageType.Error:
                    probleemGroupbox.Header = "Fout!";
                    probleemTextBox.Foreground = Brushes.DarkRed;
                    probleemImage.Source = isc.ConvertFromString("pack://application:,,,/JasRibbonApplicatie;component/Images/error.png") as ImageSource;
                    break;
            }
        }

    }

}